package com.z.kq.utils;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class DateUtils {

	/** 日期 */
	public final static String DEFAILT_DATE_PATTERN = "yyyy-MM-dd";
	/** 日期时间 */
	public final static String DEFAILT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	/** 时间 */
	public final static String DEFAULT_TIME_PATTERN = "HH:mm:ss";
	/**
	 * 每天的毫秒数
	 */
	public final static long MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
	
	
	/**
	 * 判断指定日期是否是周六，周日
	 * @param dt
	 * @return
	 * @throws Exception
	 */
	public static boolean isWeekOfDate(Date dt) {
		String str = DateUtils.convertDate2Week(dt);
        if(str.equals("星期六") || str.equals("星期日")){
        	return true;
        }else{
        	return false;
        }
    }

	/**
	 * 转换日期字符串得到指定格式的日期类型
	 * 
	 * @author zhangyv
	 * @param formatString
	 *            需要转换的格式字符串（例："yyyy-MM" or "yyyy-MM-dd" or "yyyy-MM-dd HH" 等日期的规范标记的组合）
	 * @param targetDate
	 *            需要转换的时间
	 * @return
	 * 		例	convertString2Date("2015-11-10 10:52","yyyy-MM-dd HH:mm");
	 * @throws ParseException
	 */
	public static final Date convertString2Date(String formatString, String targetDate)
			throws ParseException {
		if (StringUtils.isBlank(targetDate))
			return null;
		SimpleDateFormat format = null;
		Date result = null;
		format = new SimpleDateFormat(formatString);
		try {
			result = format.parse(targetDate);
		} catch (ParseException pe) {
			throw new ParseException(pe.getMessage(), pe.getErrorOffset());
		}
		return result;
	}

	
	/**
	 * 转换字符串得到默认格式的日期类型
	 * 
	 * @author zhangyv
	 * 
	 * @param strDate
	 * 		格式必须为:"yyyy-MM-dd"
	 * @return
	 * 		例	convertString2Date("2015-01-01");
	 * @throws ParseException
	 */
	public static Date convertString2Date(String strDate) throws ParseException {
		Date result = null;
		try {
			result = convertString2Date(DEFAILT_DATE_PATTERN, strDate);
		} catch (ParseException pe) {
			throw new ParseException(pe.getMessage(), pe.getErrorOffset());
		}
		return result;
	}
	
	
	
	
	/**
	 * 转换字符串得到其对应日期时间的一个毫秒数
	 * 
	 * @author zhangyv
	 * 
	 * @param strDate	
	 * 		需要转换日期字符串,格式必须为"yyyy-MM-dd"
	 * @return
	 * 		例	convertString2LongDate("2015-01-01");
	 * @throws ParseException
	 */
	public static Long convertString2LongDate(String strDate) throws ParseException {
		Long result = null;
		try {
			result = convertString2Date(strDate).getTime();
		} catch (ParseException pe) {
			throw new ParseException(pe.getMessage(), pe.getErrorOffset());
		}
		return result;
	}
	
	/**
	 * 转换日期字符串得到指定格式的日期类型
	 * 
	 * @author zhangyv
	 * 
	 * @param formatString
	 *            需要转换的格式字符串（例：yyyy-MM or yyyy-MM-dd or yyyy-MM-dd HH 等日期的规范标记的组合）
	 * @param targetDate
	 *            需要转换的时间
	 * @return
	 * 		例	convertString2LongDate("yyyy-MM-dd HH","2015-01-01 01");
	 * 			convertString2LongDate("yyyy-MM-dd HH:mm:ss","2015-01-01 01:20:03");
	 * @throws ParseException
	 */
	public static final Long convertString2LongDate(String formatString, String targetDate)
			throws ParseException {
		Long result = null;
		try {
			result = convertString2Date(formatString,targetDate).getTime();
		} catch (ParseException pe) {
			throw new ParseException(pe.getMessage(), pe.getErrorOffset());
		}
		return result;
	}

	/**
	 * 转换日期得到指定格式的日期字符串
	 * 
	 * @param formatString
	 *            需要把目标日期格式化什么样子的格式。例如,yyyy-MM-dd HH:mm:ss
	 * @param targetDate
	 *            目标日期
	 * @return
	 */
	public static String convertDate2String(String formatString, Date targetDate) {
		SimpleDateFormat format = null;
		String result = null;
		if (targetDate != null) {
			format = new SimpleDateFormat(formatString);
			result = format.format(targetDate);
		} else {
			return null;
		}
		return result;
	}

	/**
	 * 转换日期,得到默认日期格式字符串
	 * 
	 * @param targetDate
	 * @return
	 */
	public static String convertDate2String(Date targetDate) {
		return convertDate2String(DEFAILT_DATE_PATTERN, targetDate);
	}
	
	
	/**
	 * 获取当前日期的年月日　字符串型数据
	 * 格式为"yyyy-MM-dd"
	 * 
	 */
	public static String getCurrentDate() {
		Date date = new Date();
		return DateUtils.convertDate2String("yyyy-MM-dd",date);
	}
	
	/**
	 * 获取当前日期的年月日　时分秒为零的日期格式
	 * @throws ParseException 
	 * 
	 */
	public static Date getCurrentDate_date() throws ParseException {
		String date = getCurrentDate();
		return DateUtils.convertString2Date("yyyy-MM-dd", date);
	}
	
	/**
	 * 格式化指定日期　(按指定的格式，格式不涉及的尾部格式成0)
	 *　
	 *　
	 * @return　日期 date =　2014-12-12 12:05:85 888  
	 * 			formatDate_date("yyyy-MM-dd HH",date);
	 * 			返回值为　Date　值为　2014-12-12 12:00:00 888
	 * @throws ParseException
	 */
	public static Date formatDate_date(String formatString, Date targetDate) throws ParseException {
		String date = convertDate2String(formatString,targetDate);
		return DateUtils.convertString2Date(formatString, date);
	}
	
	/**
	 * 格式化指定日期　时分秒为零的日期
	 * @throws ParseException 
	 * 
	 */
	public static Date formatDate_date( Date targetDate) throws ParseException {
		String date = convertDate2String("yyyy-MM-dd",targetDate);
		return DateUtils.convertString2Date(date);
	}
	
	
	/**
	 * 格式化指定日期　时分秒为零的日期
	 * 格式为"yyyy-MM-dd" 
	 * 
	 */
	public static String formatDate(Date targetDate) throws ParseException {
		return DateUtils.convertDate2String("yyyy-MM-dd", targetDate);
	}
	
	
	/**
	 * 格式化指定日期　时分秒为零的日期格式
	 * 格式为"yyyy-MM-dd"
	 * 
	 */
//	public static String formatDate(String formatString, Date targetDate) throws ParseException {
//		String date = getCurrentDate();
//		return DateUtils.convertString2Date("yyyy-MM-dd", date);
//	}
	
	
	
	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的天数)
	 * 
	 * @return Date 指定的日期i天前（后）的日期
	 * 
	 *         往前或后推几日(正数往前，负数往后)
	 */
	public static Date plusDateC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusDays(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的月数)
	 * 
	 * @return Date 指定的日期i月前（后）的日期
	 * 
	 *         往前或后推月(正数往前，负数往后)
	 */
	public static Date plusMonthC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusMonths(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的年数)
	 * 
	 * @return Date 指定的日期i年前（后）的日期
	 * 
	 *         往前或后推年(正数往前，负数往后)
	 */
	public static Date plusYearC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusYears(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的小时数)
	 * 
	 * @return Date 指定的日期i小时前（后）的日期
	 * 
	 *         往前或后推小时(正数往前，负数往后)
	 */
	public static Date plusHourC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusHours(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的分钟数)
	 * 
	 * @return Date 指定的日期i分钟前（后）的日期
	 * 
	 *         往前或后推分钟(正数往前，负数往后)
	 */
	public static Date plusMinuteC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusMinutes(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d(要操作的Date对象)
	 * @param i (要推的周数)
	 * 
	 * @return Date 指定的日期i周前（后）的日期
	 * 
	 *         往前或后推周(正数往前，负数往后)
	 */
	public static Date plusWeekC(Date d, int i) {
		DateTime dt = new DateTime(d);
		dt = dt.plusWeeks(i);
		return dt.toDate();
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的天数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的天数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTDays(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Days dS = Days.daysBetween(dt, dt1);
		int kd = dS.getDays();
		return kd;
	}


	/**
	 * 作者：张雨
	 *
	 * @param d
	 * @param d1
	 *
	 * @return int 两个日期相隔的天数
	 *
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 *
	 *         比较两个时间相差的天数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int betweenDays(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Days dS = Days.daysBetween(dt, dt1);
		int kd = dS.getDays();
		return kd;
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的月数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的月数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTMonths(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Months dS = Months.monthsBetween(dt, dt1);
		int kd = dS.getMonths();
		return kd;
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的年数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的年数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTYears(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Years dS = Years.yearsBetween(dt, dt1);
		int kd = dS.getYears();
		return kd;
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的小时数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的小时数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTHours(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Hours dS = Hours.hoursBetween(dt, dt1);
		int kd = dS.getHours();
		return kd;
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的分钟数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的分钟数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTMinutes(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Minutes dS = Minutes.minutesBetween(dt, dt1);
		int kd = dS.getMinutes();
		return kd;
	}

	/**
	 * 作者：张雨
	 * 
	 * @param d
	 * @param d1
	 * 
	 * @return int 两个日期相隔的周数
	 * 
	 *         注意：这种方法返回的效果可能不是很理想，因为它们的原理是两个日期相减得到毫秒数，然后根据毫秒数再转成年、月、日、周等、
	 * 
	 *         比较两个时间相差的周数(第一个日期小于第二日期返回正数，第一个日期大于第二个日期返回负数)
	 */
	public static int bTWeeks(Date d, Date d1) {
		DateTime dt = new DateTime(d);
		DateTime dt1 = new DateTime(d1);
		Weeks dS = Weeks.weeksBetween(dt, dt1);
		int kd = dS.getWeeks();
		return kd;
	}
	
	/**
	 * 获取当前日期的星期
	 * @param date
	 * @return 当前日期星期
	 */
	public static String convertDate2Week(Date date) {
		String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int w = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (w < 0) {
			w = 0;
		}
		return weekDays[w];
	}
	
	/**
	 * 获取从指定日期向后推指定月份之间的天数
	 * @param startDay 开始日期
	 * @param monthNum 指定月份
	 * @return
	 */
	public static int getDays(String startDay, int monthNum) {
		try {
			String format = "yyyy-MM-dd";
			Date start = DateUtils.convertString2Date(format, startDay);
			Date end = DateUtils.plusMonthC(start, monthNum);
			int betweenDay = DateUtils.betweenDays(start, end);
			return betweenDay < 1 ? 0 : betweenDay;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	/**
	 * 获取指定月份的最后一天日期格式"yyyy-MM-dd"
	 * @param month 要求格式 "yyyy-MM";
	 * @return 指定月份的最后一天日期格式"yyyy-MM-dd"
	 */
	public static String getMonthLastDate(String month) {
		try {
			String[] array = month.split("-");
			int y = Integer.valueOf(array[0]);
			int m = Integer.valueOf(array[1]);
			switch (m) {
				case 2:
					if ((y % 100 == 0 && y % 400 == 0) || y % 4 == 0) {
						return month + "-" + 29;
					} 
					return month + "-" + 28;
				case 4:
				case 6:
				case 9:
				case 11:
					return month + "-" + 30;
				default:
					return month + "-" + 31;
			}
		} catch (NumberFormatException e) {
			e.printStackTrace();
		}
		return "2017-01-31";
	}
	
	/**
	 * 获取两个指定日期之间的所有日期
	 * @param start 开始日期 格式yyyy-MM-dd
	 * @param end 结束日期 格式yyyy-MM-dd
	 * @return 例如传入2017-01-01 2017-01-04 返回【2017-01-02 2017-01-03】
	 */
	public static List<String> getMiddleDate(String start, String end) {
		List<String> result = new ArrayList<String>();
		String format = "yyyy-MM-dd";
		try {
			Date startDate = DateUtils.convertString2Date(format, start);
			int days = DateUtils.betweenDays(startDate, DateUtils.convertString2Date(format, end));
			if (days > 1) {
				for (int i = 1; i < days; i++) {
					result.add(DateUtils.convertDate2String("yyyy-MM-dd", DateUtils.plusDateC(startDate, i)));
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return result;
	}



	public static void main(String[] args) {
		List<String> list = DateUtils.getMiddleDate("2017-06-28", "2017-07-03");
		for (String string : list) {
			System.out.println(string);
		}
		

	}

	public static String getCurrentDateTime() {
		return DateUtils.convertDate2String("yyyy-MM-dd HH:mm:ss", new Date());
	}

}
